package com.unismc.charge.collector.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitee.loyo.Request;
import com.gitee.loyo.Result;
import com.gitee.loyo.StationService;
import com.gitee.loyo.config.properties.ChargeCoordinationProperty;
import com.gitee.loyo.config.properties.ChargeProperties;
import com.gitee.loyo.config.properties.ChargeQueryProperty;
import com.gitee.loyo.data.StationInfo;
import com.gitee.loyo.data.StationStatsInfo;
import com.gitee.loyo.post.QueryStationStatsPost;
import com.gitee.loyo.post.QueryStationStatusPost;
import com.gitee.loyo.post.QueryStationsPost;
import com.gitee.loyo.result.QueryStationStatsResult;
import com.gitee.loyo.result.QueryStationStatusResult;
import com.gitee.loyo.result.QueryStationsResult;
import com.unismc.charge.collector.cache.ChargeInfoCache;
import com.unismc.charge.collector.service.QueryService;
import com.unismc.charge.collector.utils.SpringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: Forward Seen
 * @description:
 * @createTime: 2024/4/29 10:45
 * @since: 1.0
 */
@Slf4j
@Service
public class QueryServiceImpl implements QueryService {

    @Resource
    private StationService stationService;
    @Resource
    private ChargeProperties chargeProperties;
    @Resource
    private ObjectMapper objectMapper;

    private static final Map<String, List<String>> stationCache = ChargeInfoCache.stationIdCache;

    @Override
    public void queryStationsInfo() {
        log.info("初始化获取所有充电站信息......");
        Set<String> operatorKeys = chargeProperties.getOperatorKeys();
        for (String operatorKey : operatorKeys) {
            ChargeCoordinationProperty coordinationProperty = chargeProperties.getCoordinationProperty(operatorKey);
            log.info("开始向对接方（operatorKey）{}【{}】请求查询充电站信息......", operatorKey, coordinationProperty.getOperatorName());
            ChargeQueryProperty queryProperty = chargeProperties.getQueryProperty(operatorKey);
            queryStationsInfoPageAndPush(operatorKey, queryProperty.getOperatorId(), 1, 10);
            log.info("完成对接方（operatorKey）{}【{}】充电站信息查询！", operatorKey, coordinationProperty.getOperatorName());
        }
    }

    @SneakyThrows(Exception.class)
    public void queryStationsInfoPageAndPush(String operatorKey, String operatorId, Integer pageNo, Integer pageSize) {
        log.info("正在获取运营商{}第{}页充电站信息", operatorKey, pageNo);
        QueryStationsPost post = new QueryStationsPost().setPageNo(pageNo).setPageSize(pageSize);
        Result<QueryStationsResult> result = stationService.queryStationsInfo(new Request<>(operatorId, post), operatorKey);
        log.info("成功获取运营商{}第{}页充电站信息:{}", operatorKey, pageNo, objectMapper.writeValueAsString(result));
        QueryStationsResult data = result.getData();
        if (data == null) {
            return;
        }
        //推送
        SpringUtils.ctx().publishEvent(data);
        //缓存
        ChargeInfoCache.put(operatorKey, data.getStationInfos());
        if (pageNo < data.getPageCount()) {
            queryStationsInfoPageAndPush(operatorKey, operatorId, ++pageNo, pageSize);
        }
    }

    @Override
    public void queryStationsStatus() {
        log.info("查询所有设备接口状态......");
        Set<String> operatorKeys = chargeProperties.getOperatorKeys();
        for (String operatorKey : operatorKeys) {
            ChargeCoordinationProperty coordinationProperty = chargeProperties.getCoordinationProperty(operatorKey);
            log.info("开始向对接方（operatorKey）{}【{}】请求查询充电设备接口状态信息......", operatorKey, coordinationProperty.getOperatorName());
            ChargeQueryProperty queryProperty = chargeProperties.getQueryProperty(operatorKey);
            queryStationsStatusAndPush(operatorKey, queryProperty.getOperatorId(), 50);
            log.info("完成对接方（operatorKey）{}【{}】充电站设备接口状态信息查询！", operatorKey, coordinationProperty.getOperatorName());
        }
    }

    @SneakyThrows(Exception.class)
    public void queryStationsStatusAndPush(String operatorKey, String operatorId, int batchSize) {
        List<String> stationIds = stationCache.get(operatorKey);
        if (CollectionUtils.isEmpty(stationIds)) {
            return;
        }
        //每次最多查询50个厂站，分批查询
        int startIndex = 0;
        while (startIndex < stationIds.size()) {
            int endIndex = Math.min(startIndex + batchSize, stationIds.size());
            List<String> sendBatchIds = stationIds.subList(startIndex, endIndex);
            //查询
            QueryStationStatusPost post = new QueryStationStatusPost().setStationIds(sendBatchIds);
            Result<QueryStationStatusResult> result = stationService.queryStationStatus(new Request<>(operatorId, post), operatorKey);
            log.info("成功获取运营商{}充电站设备接口状态信息:{}", operatorKey, objectMapper.writeValueAsString(result));
            QueryStationStatusResult data = result.getData();
            SpringUtils.ctx().publishEvent(data);

            startIndex += batchSize;
        }

    }

    @Override
    public void queryStationsStats() {
        log.info("查询所有统计信息......");
        Set<String> operatorKeys = chargeProperties.getOperatorKeys();
        String startTime = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String endTime = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        for (String operatorKey : operatorKeys) {
            ChargeCoordinationProperty coordinationProperty = chargeProperties.getCoordinationProperty(operatorKey);
            log.info("开始向对接方（operatorKey）{}【{}】查询统计信息......", operatorKey, coordinationProperty.getOperatorName());
            ChargeQueryProperty queryProperty = chargeProperties.getQueryProperty(operatorKey);
            queryStationStatsAndPush(operatorKey, queryProperty.getOperatorId(), startTime, endTime);
            log.info("完成对接方（operatorKey）{}【{}】统计信息查询！", operatorKey, coordinationProperty.getOperatorName());
        }
    }

    @SneakyThrows(Exception.class)
    public void queryStationStatsAndPush(String operatorKey, String operatorId, String startTime, String endTime) {
        List<String> stationIds = stationCache.get(operatorKey);
        if (CollectionUtils.isEmpty(stationIds)) {
            return;
        }
        for (String stationId : stationIds) {
            QueryStationStatsPost post = new QueryStationStatsPost()
                    .setStationId(stationId)
                    .setStartTime(startTime)
                    .setEndTime(endTime);
            Result<QueryStationStatsResult> result = stationService.queryStationStats(new Request<>(operatorId, post), operatorKey);
            log.info("成功获取运营商{}充电站{}统计信息:{}", operatorKey, stationId, objectMapper.writeValueAsString(result));
            StationStatsInfo data = result.getData().getStationStats();
            SpringUtils.ctx().publishEvent(data);
        }
    }

}
